home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / doc.lha / doc.doc / toolsupp.doc < prev    next >
Text File  |  1992-09-25  |  44KB  |  1,179 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11. ___________________________________________________________________
  12.  
  13.  
  14.                                    Tool Support for
  15.                                    Data Structures
  16.  
  17.                                    J. Grosch
  18.  
  19.  
  20. ___________________________________________________________________
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50. ___________________________________________________________________
  51.                                    GESELLSCHAFT FUeR MATHEMATIK
  52.                                    UND DATENVERARBEITUNG MBH
  53.  
  54.                                    FORSCHUNGSSTELLE FUeR
  55.                                    PROGRAMMSTRUKTUREN
  56.                                    AN DER UNIVERSITAeT KARLSRUHE
  57. ___________________________________________________________________
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.                                    Project
  76.  
  77.                              Compiler Generation
  78.  
  79.          ___________________________________________________________
  80.  
  81.                        Tool Support for Data Structures
  82.  
  83.  
  84.                                  Josef Grosch
  85.  
  86.  
  87.                                  Nov. 8, 1989
  88.  
  89.          ___________________________________________________________
  90.  
  91.  
  92.                                 Report No. 17
  93.  
  94.  
  95.                              Copyright c 1989 GMD
  96.  
  97.  
  98.             Gesellschaft fuer Mathematik und Datenverarbeitung mbH
  99.                 Forschungsstelle an der Universitaet Karlsruhe
  100.                           Vincenz-Priesznitz-Str. 1
  101.                                D-7500 Karlsruhe
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.                                                                              1
  135.  
  136.  
  137.                        Tool Support for Data Structures
  138.  
  139.                                  Josef Grosch
  140.               GMD Forschungsstelle an der Universitaet Karlsruhe
  141.              Vincenz-Priesznitz-Str. 1, D-7500 Karlsruhe, Germany
  142.                               Tel: +721-6622-26
  143.                        E-Mail: grosch@karlsruhe.gmd.de
  144.  
  145.  
  146. Abstract   Linked records are a general mechanism  to  build  data  structures
  147. like lists, trees, and graphs. Most high-level programming languages only pro-
  148. vide the definition of record types, an operator for component selection,  and
  149. allocation  of record storage. We propose to specify complete graph structures
  150. by context-free grammars. A tool can be used to transform such a specification
  151. into  a  set  of  record  type declarations and program code for features like
  152. denotations for record values, input and output for record values and complete
  153. graphs,  or  interactive browsers for data structures. We describe such a tool
  154. called ast (generator for abstract syntax trees), its specification  language,
  155. the  advantages  of this approach, and our current experiences. Currently, the
  156. main application is the specification  of  attributed  abstract  syntax  trees
  157. within compilers. We finally discuss the relationship to related work.
  158.  
  159. 1.  Introduction
  160.  
  161.      Linked records are a general mechanism  to  build  data  structures  like
  162. lists,  trees,  and graphs. Most high-level programming languages only provide
  163. the definition of record types, an operator for component selection, and allo-
  164. cation  of  record storage. Therefore, the treatment of compound data types in
  165. most high-level languages can be considered to be quite  "low-level".   Excep-
  166. tions  are  very-high-level  languages  like e. g. SETL [SDD86] which provides
  167. denotations (aggregates) and input/output operations for values  of  all  data
  168. types, even compound ones like tuples, arrays, or sets.
  169.  
  170.      We propose to raise the  level  of  conventional  languages  somewhat  by
  171. improving  the  declarations  of  data  structures and by extending the set of
  172. operations available for compound data types. Declarations should  not  merely
  173. describe  single  records  but  also  the relationships among them. Additional
  174. operations include denotations for record values (aggregates) as well as input
  175. and  output  for record values or complete data structures like graphs.  More-
  176. over, it is desirable to have commonly used operations for general data struc-
  177. tures.   These could range from reversing the elements of lists to interactive
  178. browsers for graphs which allow the inspection of the values of all fields  of
  179. the nodes in a user-driven dialogue.
  180.  
  181.      The structure of graphs can be  specified  conveniently  by  context-free
  182. grammars. A grammar rule describes a node type and a nonterminal a set of node
  183. types.
  184.  
  185.      The  above  features  could  be  incorporated  into  existing  or  future
  186. languages.   This  would of course be the kind of realization to prefer.  How-
  187. ever, today we have to live with languages like Modula-2 or  C  without  those
  188. features. Therefore, a tool could produce a program module written in the con-
  189. crete target language which defines the specified data structure by a  set  of
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.                                                                              2
  201.  
  202.  
  203. record  declarations  and  which  implements the additional operations by gen-
  204. erated procedures.  This  has  the  advantage  that  no  changes  to  existing
  205. languages are necessary.
  206.  
  207.      This paper presents such a tool called ast: generator for abstract syntax
  208. trees  [Gro91].   The tool's name is derived from its main application in com-
  209. piler construction where it is used for attributed abstract syntax trees.  ast
  210. is  implemented  in Modula-2 as well as in C under UNIX and generates Modula-2
  211. or C source modules. We describe the specification language of the  tool,  its
  212. output,   its  advantages,  and  our  experiences.  We  also  discuss  related
  213. approaches.  In the following we talk only about the data  structure  directed
  214. graph  because  lists  and  trees  are special cases thereof. The examples use
  215. Modula-2 as target language.
  216.  
  217. 2.  Specification Language
  218.  
  219.      The structure of directed graphs is specified by  a  formalism  based  on
  220. context-free  grammars.   However, we use the classical terminology for graphs
  221. in defining the specification language. Its relationship to context-free gram-
  222. mars is discussed later.
  223.  
  224. 2.1.  Node Types
  225.  
  226.      A directed graph consists of nodes.  A node may be related to other nodes
  227. in  a  so-called parent-child relation. Then the first node is called a parent
  228. node and the latter nodes are called child nodes. Nodes without a parent  node
  229. are usually called root nodes, nodes without children are called leaf nodes.
  230.  
  231.      The structure and the properties of nodes are described  by  node  types.
  232. Every  node  belongs  to  a node type.  A specification of a graph describes a
  233. finite number of node types.  A node type specifies the  names  of  the  child
  234. nodes and the associated node types as well as the names of the attributes and
  235. the associated attribute types.
  236.  
  237. 2.2.  Children
  238.  
  239.      Children are distinguished by selector names which have to be unambiguous
  240. within one node type.  The children are of a certain node type.
  241.  
  242.     Example:
  243.        If        = Expr: Expr Then: Stats Else: Stats .
  244.        While     = Expr: Expr Stats: Stats .
  245.  
  246. The example introduces two node types called If and While.  A node of type  If
  247. has  three children which are selected by the names Expr, Then, and Else.  The
  248. children have the node types Expr, Stats, and Stats.  If a  selector  name  is
  249. equal  to  the  associated name of the node type it can be omitted. Therefore,
  250. the above example can be abbreviated as follows:
  251.  
  252.        If        = Expr Then: Stats Else: Stats .
  253.        While     = Expr Stats .
  254.  
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.                                                                              3
  266.  
  267.  
  268. 2.3.  Attributes
  269.  
  270.      As well as children, every node type can specify an arbitrary  number  of
  271. attributes  of arbitrary types. Like children, attributes are characterized by
  272. a selector name and a  certain  type.   The  descriptions  of  attributes  are
  273. enclosed  in  brackets.  The attribute types are given by names taken from the
  274. target language. Missing attribute types are assumed  to  be  int  or  INTEGER
  275. depending on the target language (C or Modula-2).  Children and attributes can
  276. be given in any order.  The type of an attribute can be a pointer  to  a  node
  277. type.  In contrast to children, ast does not follow such an attribute during a
  278. graph traversal. All attributes are considered to be neither  tree  nor  graph
  279. structured.  Only  the  user knows about this fact and therefore he/she should
  280. take care.
  281.  
  282.     Example:
  283.        Binary    = Lop: Expr Rop: Expr [Operator: INTEGER] .
  284.        Unary     = Expr [Operator] .
  285.        IntConst  = [Value] .
  286.        RealConst = [Value: REAL] .
  287.  
  288.  
  289. 2.4.  Extensions
  290.  
  291.      To allow several alternatives for the  types  of  children  an  extension
  292. mechanism is used. A node type may be associated with several other node types
  293. enclosed in angle brackets. The first node type is called base or  super  type
  294. and the latter types are called derived types or subtypes.  A derived type can
  295. in turn be extended with no limitation of the nesting  depth.   The  extension
  296. mechanism  induces  a  subtype  relation between node types.  This relation is
  297. transitive.  Where a node of a certain node type is required, either a node of
  298. this node type or a node of a subtype thereof is possible.
  299.  
  300.     Example:
  301.     Stats        = <
  302.        If        = Expr Then: Stats Else: Stats .
  303.        While     = Expr Stats .
  304.     > .
  305.  
  306.  
  307.      In the above example Stats is a base type describing nodes  with  neither
  308. children nor attributes.  It has two derived types called If and While.  Where
  309. a node of type Stats is required, nodes of types Stats, If, and While are pos-
  310. sible.   Where  a  node of type If is required, nodes of type If are possible,
  311. only.
  312.  
  313.      Besides extending the set of possible node types, the extension mechanism
  314. has  the  property  of extending the children and attributes of the base type.
  315. The derived types possess the children and attributes of the base type.   They
  316. may define additional children and attributes. In other words they inherit the
  317. structure of the base type.  The selector names of all children and attributes
  318. in  an  extension hierarchy have to be distinct.  The syntax has been designed
  319. this way in order to allow single inheritance, only.
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.                                                                              4
  331.  
  332.  
  333.     Example:
  334.     Stats        = Next: Stats [Position: tPosition] <
  335.        If        = Expr Then: Stats Else: Stats .
  336.        While     = Expr Stats .
  337.     > .
  338.  
  339.  
  340.      Nodes of type Stats have one child selected by  the  name  Next  and  one
  341. attribute  named  Position.   Nodes of type While have three children with the
  342. selector names Next, Expr, and Stats and one attribute named Position.
  343.  
  344.      A node of a base type like Stats usually does not occur  in  an  abstract
  345. syntax  tree  for  a  complete program.  Still, ast defines this node type. It
  346. could be used as placeholder for unexpanded nonterminals  in  incomplete  pro-
  347. grams which occur in applications like syntax directed editors.
  348.  
  349. 2.5.  Modules
  350.  
  351.      The specification of node types can be grouped into modules. This feature
  352. can  be  used  to structure a specification or to extend an existing one. If a
  353. node type has already been declared the given children, attributes, and exten-
  354. sions  are  added  to  the existing declaration.  Otherwise a new node type is
  355. introduced.
  356.  
  357.     Example:
  358.     MODULE my_version
  359.     Stats        = [Env: tEnv] <                    /* add attribute */
  360.        While     = Init: Stats Terminate: Stats .   /* add children  */
  361.        Repeat    = Stats Expr .                     /* add node type */
  362.     > .
  363.     END my_version
  364.  
  365.  
  366. 2.6.  Properties
  367.  
  368.      Children and attributes can be given several properties by attaching key-
  369. words  like  INPUT  or  REVERSE.   Input  attributes  receive a value at node-
  370. creation time, whereas non-input attributes may receive their values at  later
  371. times.  Input attributes are included into the parameter list of the node con-
  372. structor procedures (see section 3). As a shorthand, every  list  of  children
  373. and  attributes  may  contain the symbol '->' to separate input from non-input
  374. items.  The property reverse specifies how lists should  be  reversed.  It  is
  375. discussed in the next section.
  376.  
  377. 2.7.  Reversal of Lists
  378.  
  379.      Recursive node types like Stats in the abstract grammar  of  the  example
  380. below describe lists of subtrees.  There are some cases where it is convenient
  381. to be able to easily reverse the order of the subtrees in a list. The facility
  382. provided by ast is a generalization of an idea presented in [Par88].
  383.  
  384.  
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.                                                                              5
  394.  
  395.  
  396.      Using LR parsers, one might be forced to  parse  a  list  using  a  left-
  397. recursive  concrete  grammar rule because of the limited stack size.  The con-
  398. crete grammar rules of  the  following  examples  are  written  in  the  input
  399. language  of  the parser generator lalr [Gro88, GrV88] which is similar to the
  400. one of YACC [Joh75]. The  node  constructor  procedures  within  the  semantic
  401. actions are the ones provided by ast (see section 3).
  402.  
  403.     Example:
  404.     concrete grammar (with tree building actions):
  405.     Stats:                         {$$ := mStats0 ();      } .
  406.     Stats: Stats Stat ';'          {$$ := mStats1 ($2, $1);} .
  407.     Stat : WHILE Expr DO Stats END {$$ := mWhile  ($2, ReverseTREE ($4));} .
  408.  
  409.  
  410.     abstract grammar:
  411.     Stats        = <
  412.        Stats0    = .
  413.        Stats1    = Stat Stats REVERSE .
  414.     > .
  415.  
  416. Without the call of the procedure  ReverseTREE  and  the  property  REVERSE  a
  417. parser  using the above concrete grammar would construct statement lists where
  418. the list elements are in the wrong order, because the last  statement  in  the
  419. source  would  be the first one in the list. The WHILE rule represents a loca-
  420. tion where statement lists are used.
  421.  
  422.      To easily solve this problem, ast can generate  a  procedure  to  reverse
  423. lists.   The  specification  has to describe how this should be done.  At most
  424. one child of every node type may be given the property reverse.  The generated
  425. list  reversal procedure ReverseTREE then reverses a list with respect to this
  426. indicated child.  The procedure ReverseTREE has to be called exactly once  for
  427. a  list to be reversed. This is the case at the location where a complete list
  428. is included as subtree (e. g. in a WHILE statement).
  429.  
  430. 2.8.  Target Code
  431.  
  432.      An ast specification may include sections containing target code.  Target
  433. code  is  code  written  in  the target language which is copied unchecked and
  434. unchanged to certain places in the generated module.  Target code can be  used
  435. for  import  or  export statements, for the declaration of global variables or
  436. procedures, and for statements to initialize or  finalize  the  declared  data
  437. structures.
  438.  
  439. 2.9.  Type Specific Operations
  440.  
  441.      Procedures generated by ast apply seven operations  to  attributes:  ini-
  442. tialization,  finalization,  ascii  read and write, binary read and write, and
  443. copy (see Table 1).  Initialization is performed whenever a node  is  created.
  444. It  can  range  from  assigning  an initial value to the allocation of dynamic
  445. storage or the construction of complex data structures.  Finalization is  per-
  446. formed  immediately before a node is deleted and may e. g. release dynamically
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.                                                                              6
  458.  
  459.  
  460. allocated space. The read and write operations enable the readers and  writers
  461. to  handle  the  complete  nodes including all attributes, even those of user-
  462. defined types.  The operation copy is needed to duplicate values of attributes
  463. of  user-defined  types. By default, ast just copies the bytes of an attribute
  464. to duplicate it.  Therefore, pointer semantics is assumed for attributes of  a
  465. pointer  type.   If value semantics is needed, the user has to take care about
  466. this operation.
  467.  
  468.      The operations are type specific in the sense that every type has its own
  469. set  of operations. All attributes having the same type (target type name) are
  470. treated in the same way. Chosing different type names for one type  introduces
  471. subtypes  and  allows  to  treat attributes of different subtypes differently.
  472. Type operations for the predefined types of a target language  are  predefined
  473. within ast.  For user-defined types, ast assumes default operations (see Table
  474. 1).  The procedures yyReadHex and yyWriteHex read and write the  bytes  of  an
  475. attribute  as  hexadecimal  values.   The  procedures yyGet and yyPut read and
  476. write the bytes of an attribute unchanged (without  conversion).   The  opera-
  477. tions are defined by a macro mechanism.  TYPE is replaced by the concrete type
  478. name.  a is a formal macro parameter referring to the attribute.  It is possi-
  479. ble  to  redefine the operations by including new macro definitions written in
  480. cpp syntax.
  481.  
  482.                       Table 1: Type specific operations
  483.  
  484.                                                      default macro
  485.   operation       macro name                  C                    Modula-2
  486. _______________________________________________________________________________
  487. initialization   beginTYPE(a)
  488. finalization     closeTYPE(a)
  489. ascii read       readTYPE(a)    yyReadHex (& a, sizeof (a));    yyReadHex (a);
  490. ascii write      writeTYPE(a)   yyWriteHex (& a, sizeof (a));   yyWriteHex (a);
  491. binary read      getTYPE(a)     yyGet (& a, sizeof (a));        yyGet (a);
  492. binary write     putTYPE(a)     yyPut (& a, sizeof (a));        yyPut (a);
  493. copy             copyTYPE(a)
  494.               
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.                              
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.                                                              
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521. 3.  Generated Program Module and its Use
  522.  
  523.      A specification as described in the previous section is translated by ast
  524. into  a  program module consisting of a definition and an implementation part.
  525. Only the definition part is sketched here.  The definition part contains  pri-
  526. marily type declarations to describe the structure of the graphs and the head-
  527. ings of the generated procedures.
  528.  
  529.      Every node type is turned  into  a  constant  declaration  and  a  record
  530. (struct)  declaration.  That  is  quite  simple, because node types and record
  531. declarations are almost the same concepts except for the  extension  mechanism
  532. and  some  shorthand notations.  All these records become members of a variant
  533. record (union) used to describe graph nodes in general.  This  variant  record
  534. has a tag field called Kind which stores the code of the node type.  A pointer
  535. to the variant record is a  type  representing  graphs.   Like  all  generated
  536.  
  537.  
  538.  
  539.  
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.                                                                              7
  547.  
  548.  
  549.  
  550.                   Table 2: Generated objects and procedures
  551.  
  552. object/procedure    description
  553. _________________________________________________________________________________________
  554. <node type>         named constant to encode a node type
  555. tTREE               pointer type, refers to variant record type describing all node types
  556. TREERoot            variable of type tTREE, can serve as root
  557.                     (additional variables can be declared)
  558. _________________________________________________________________________________________
  559. MakeTREE            node constructor procedure without attribute initialization
  560. n<node type>        node constructor procedures with attribute initialization
  561.                     according to the type specific operations
  562. m<node type>        node constructor procedures with attribute initialization
  563.                     from a parameter list for input attributes
  564. ReleaseTREE         node or graph finalization procedure,
  565.                     all attributes are finalized, all node space is deallocated
  566. ReleaseTREEModule   deallocation of all graphs managed by a module
  567. WriteTREENode       ASCII node writer procedure
  568. ReadTREE            ASCII graph reader procedure
  569. WriteTREE           ASCII graph writer procedure
  570. GetTREE             binary graph reader procedure
  571. PutTREE             binary graph writer procedure
  572. ReverseTREE         procedure to reverse lists
  573. TraverseTREETD      top down graph traversal procedure (reverse depth first)
  574. TraverseTREEBU      bottom up graph traversal procedure (depth first search)
  575. CopyTREE            graph copy procedure
  576. CheckTREE           graph syntax checker procedure
  577. QueryTREE           graph browser procedure
  578. BeginTREE           procedure to initialize user-defined data structures
  579. CloseTREE           procedure to finalize user-defined data structures
  580.                  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602.  
  603.  
  604.  
  605.  
  606.  
  607.  
  608.  
  609. names, this pointer type is derived from the name of the specification.  Table
  610. 2  briefly  explains  the  exported objects.  Their generation is requested by
  611. simple command line options.
  612.  
  613.      The parameters of the procedures m<node type> have to  be  given  in  the
  614. order  of  the  input  attributes in the specification. Attributes of the base
  615. type (recursively) precede the ones  of  the  derived  type.   The  procedures
  616. TraverseTREETD  and TraverseTREEBU visit all nodes of a graph. At every node a
  617. procedure given as parameter is executed. An assignment of a graph to a  vari-
  618. able of type tTREE can be done in two ways: The usual assignment operators '='
  619. or ':=' yield pointer semantics. The procedure CopyTREE yields value semantics
  620. by duplicating a given graph.
  621.  
  622.      The procedure QueryTREE allows to browse a graph and to inspect one  node
  623. at  a  time. A node including the values of its attributes is printed on stan-
  624. dard output.  Then the user is prompted to provide one of the  following  com-
  625. mands from standard input:
  626.  
  627.  
  628.  
  629.  
  630.  
  631.  
  632.  
  633.  
  634.  
  635.  
  636.  
  637.  
  638.  
  639.                                                                              8
  640.  
  641.  
  642.     parent      display parent node
  643.     quit        quit procedure QueryTREE
  644.     <selector>  display specified child
  645.  
  646.  
  647.      Unfortunately, the typing rules of ast (see  section  2.4.)  can  not  be
  648. mapped  to  every target language. For example the subtype relation can not be
  649. expressed in Modula-2. A subtype has to be compatible with its base type.  Two
  650. subtypes  of one base type have to be incompatible.  As a compromise, all node
  651. types without base types could be  implemented  by  different  pointer  types.
  652. Extensions of a base type would be mapped to the same pointer type as the base
  653. type. This solution would implement half of ast's typing rules through  static
  654. typing  of  the  target  language. For a full implementation, target languages
  655. with subtypes such as Oberon or C++ are necessary.
  656.  
  657.      The current implementation of ast omits static type checking.  It  offers
  658. dynamic  type checking through the procedure CheckTREE.  This procedure has to
  659. be called explicitly to check if a graph is properly typed. In case of  typing
  660. errors the involved parent and child nodes are printed on standard error.
  661.  
  662.      The remainder of this section explains how to use the generated  objects,
  663. presents  the  advantages  of this approach, and reports early experience with
  664. the method.
  665.  
  666.      Trees or graphs are created by successively  creating  their  nodes.  The
  667. easiest  way is to call the constructor procedures m<node type>. These combine
  668. node creation, storage allocation, and attribute assignment.  They  provide  a
  669. mechanism similar to record aggregates. Nested calls of constructor procedures
  670. allow programming with (ground) terms as in Prolog or LISP. The type of a node
  671. can  be  retrieved  by  examination  of  the predefined tag field called Kind.
  672. Children and attributes can be accessed  using  two  record  selections.   The
  673. first  one  states the node type and the second one gives the selector name of
  674. the desired item.
  675.  
  676.     Example:
  677.     abstract syntax:
  678.     Expr         = [Position: tPosition] <
  679.        Binary    = Lop: Expr Rop: Expr [Operator: INTEGER] .
  680.        Unary     = Expr [Operator] .
  681.        IntConst  = [Value] .
  682.        RealConst = [Value: REAL] .
  683.     > .
  684.  
  685.  
  686.     tree construction by a term:
  687.     CONST Plus = 1;
  688.     VAR t: tTREE; Pos: tPosition;
  689.     t := mBinary (Pos, mIntConst (Pos, 2), mIntConst (Pos, 3), Plus);
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.                                                                              9
  703.  
  704.  
  705.     tree construction during parsing:
  706.     Expr: Expr '+' Expr {$$.Tree := mBinary ($2.Pos, $1.Tree, $3.Tree, Plus);} .
  707.     Expr:      '-' Expr {$$.Tree := mUnary  ($1.Pos, $2.Tree, Minus);        } .
  708.     Expr: IntConst      {$$.Tree := mIntConst ($1.Pos, $1.IntValue);         } .
  709.     Expr: RealConst     {$$.Tree := mRealConst ($1.Pos, $1.RealValue);       } .
  710.  
  711.  
  712.     access of tag field, children, and attributes:
  713.     CASE t^.Kind OF
  714.     | Expr  : ... t^.Expr.Position             ...
  715.     | Binary: ... t^.Binary.Operator           ...
  716.               ... t^.Binary.Lop                ...
  717.     | Unary : ... t^.Unary.Expr^.Expr.Position ...
  718.     END;
  719.  
  720.  
  721.      ast can be used not only for abstract syntax trees in compilers  but  for
  722. every  tree  or  graph  like data structure. In general the data structure can
  723. serve as interface between phases within a program or  between  separate  pro-
  724. grams.   In the latter case it would be communicated via a file using the gen-
  725. erated reader and writer procedures.
  726.  
  727.      Generated tree respectively graph modules have successfully been used  in
  728. compilers  e. g. for MiniLAX [WGS89] and UNITY [Bie89] as well as for a Modula
  729. -> C translator [Mar90].  The modules for the internal data structure  of  ast
  730. itself  and  the  attribute evaluator generator ag [Gro89] have also been gen-
  731. erated by ast.  Moreover, the symbol table module of the Modula -> C  transla-
  732. tor has been generated.
  733.  
  734.      The advantage of this approach is that it saves considerably  hand-coding
  735. of  trivial  declarations  and operations. Table 3 lists the sizes (numbers of
  736. lines) of some specifications and the generated modules.  Sums in the specifi-
  737. cation  column  are composed of the sizes for the definition of node types and
  738. for user-supplied target code.  Sums in the tree module column are composed of
  739. the  sizes for the definition part and for the implementation part.  The large
  740. sizes of the tree modules are due to the numerous node constructor  procedures
  741. and  from  the graph browser in the case of ag.  These procedures proved to be
  742. very helpful for debugging purposes as they provide readable output of complex
  743. data structures.
  744.  
  745.                     Table 3: Examples of ast applications
  746.  
  747.            application            specification         tree module
  748.            ________________________________________________________
  749.            MiniLAX                           56   202 +  835 = 1037
  750.            UNITY                            210   207 +  962 = 1169
  751.            Modula -> C                      240   583 + 3083 = 3666
  752.            ag                    78 + 347 = 425   317 + 1317 = 1634
  753.            Symbol table          82 + 900 = 982   399 + 1431 = 1830
  754.                               
  755.  
  756.  
  757.  
  758.  
  759.                                                
  760.  
  761.  
  762.  
  763.  
  764.  
  765.  
  766.  
  767.  
  768.  
  769.  
  770.  
  771.  
  772.  
  773.  
  774.  
  775.  
  776.  
  777.                                                                             10
  778.  
  779.  
  780.      The realization of the presented concepts by a preprocessor leads to  the
  781. mixture  of  generated  and hand-written program code. The debugging of such a
  782. program may be problematic. Of course, the pure generated parts  are  correct.
  783. With the possibility to insert target code and type specific operations errors
  784. might be introduced. These are detected by the compiler or during run time and
  785. reported  with respect to the generated program code instead of the specifica-
  786. tion. Therefore, errors in this situation are  hard  to  debug.  This  problem
  787. could  be  solved  by  incorporating  the  concepts into a language instead of
  788. implementing them by a preprocessor.
  789.  
  790. 4.  Related Research
  791.  
  792. 4.1.  Variant Records
  793.  
  794.      ast specifications and variant record types like  in  Pascal  [JWM85]  or
  795. Modula-2  [Wir85]  are  very  similar. Every node type in an ast specification
  796. corresponds to a single variant. In the generated code,  every  node  type  is
  797. translated  into  a  record type. All record types become members of a variant
  798. record type representing the type for the graph nodes.
  799.  
  800.      The differences are the following: ast specifications  are  shorter  than
  801. directly  hand-written  variant record types.  They are based on the formalism
  802. of context-free grammars (see section below).  The generator ast automatically
  803. provides  operations  on  record types which would be simple but voluminous to
  804. program by hand. The node constructor procedures allow programming with record
  805. aggregates and provide dynamic storage management.  The reader and writer pro-
  806. cedures supply input and output for record types and even for complete  linked
  807. data structures such as trees and graphs.
  808.  
  809. 4.2.  Type Extensions
  810.  
  811.      Type extensions have been introduced with the  language  Oberon  [Wir88a,
  812. Wir88b,  Wir88c].   The extension mechanism of ast is basically the same as in
  813. Oberon.  The notions extension, base type, and  derived  type  are  equivalent
  814. (see Table 4).  Type tests and type guards are not supported by ast.  They can
  815. be programmed by inspecting the tag field of a node.   ast  does  not  provide
  816. assignment of subtypes to base types in the sense of value semantics or a pro-
  817. jection, respectively.  The tool can be seen as a preprocessor providing  type
  818. extensions for Modula-2 and C.
  819.  
  820.      The second example in section 2.4. illuminates the  relationship  between
  821. ast  and  Oberon.  The node type Stats is a base type with two fields, a child
  822. and an attribute.  It is extended e. g. by the node type While with  two  more
  823. fields representing children.
  824.  
  825. 4.3.  Context-Free Grammars
  826.  
  827.      As already mentioned, ast specifications are based on context-free  gram-
  828. mars.   ast  specifications extend context-free grammars by selector names for
  829. right-hand side symbols, attributes, the extension mechanism, and modules.  If
  830. the  features  are  omitted we basically arrive at context-free grammars. This
  831. holds from the syntactic as well as from the semantic point of view. The names
  832. of  the  node  types  represent  both terminal or nonterminal symbols and rule
  833.  
  834.  
  835.  
  836.  
  837.  
  838.  
  839.  
  840.  
  841.  
  842.  
  843.                                                                             11
  844.  
  845.  
  846. names.  Node types correspond to grammar rules. The notions of derivation  and
  847. derivation tree can be used similarly in both cases. The selector names can be
  848. seen as syntactic sugar and the attributes as some kind of  terminal  symbols.
  849. The  extension  mechanism  is equivalent to a shorthand notation for factoring
  850. out common rule parts in combination with implicit chain rules.
  851.  
  852.      Again referring to the second example in section 2.4., Stats  corresponds
  853. to  a nonterminal. There are two rules or right-hand sides for Stats which are
  854. named If and While.  The latter would be regarded as nonterminals, too,  if  a
  855. child of type If or While would be specified.
  856.  
  857. 4.4.  Attribute Grammars
  858.  
  859.      Attribute grammars [Knu68, Knu71] and ast  specifications  are  based  on
  860. context-free  grammars and associate attributes with terminal and nonterminals
  861. symbols. Additionally, ast allows attributes which are local to rules.  As the
  862. structure  of  the  tree  itself  is  known  and  transparent, subtrees can be
  863. accessed or created dynamically and used as attribute values.  The  access  of
  864. the  right-hand  side  symbols  uses  the  selector  names for symbolic access
  865. instead of the grammar symbols with an additional subscript if needed.   There
  866. is no need to map chain rules to tree nodes because of the extension mechanism
  867. offered by ast.  Attribute evaluation is outside the scope of ast.   This  can
  868. be  done either with the attribute evaluator generator ag [Gro89] which under-
  869. stands  ast  specifications  extended  by  attribute  computation  rules   and
  870. processes  the  trees generated by ast or by hand-written programs that use an
  871. ast generated module. In the latter case attribute computations do not have to
  872. obey the single assignment restriction for attributes. They can assign a value
  873. to an attribute zero, once, or several times.
  874.  
  875. 4.5.  Interface Description Language (IDL)
  876.  
  877.      The approach of ast is similar to the one of IDL  [Lam87,  NNG89].   Both
  878. specify attributed trees as well as graphs.  Node types without extensions are
  879. called nodes in IDL and node types with extensions  (base  types)  are  called
  880. classes.  ast has simplified this to the single notion of a node type.  Attri-
  881. butes are treated similarly in both systems.  Children and attributes are both
  882. regarded  as attributes, as structural and non-structural ones, with only lit-
  883. tle difference in between.  Whereas IDL in general allows multiple inheritance
  884. of  attributes,  ast  is  restricted to single inheritance and uses the notion
  885. extension instead [Wir88a].  IDL knows the predefined types INTEGER, RATIONAL,
  886. BOOLEAN,  STRING,  SEQ  OF,  and  SET OF. It offers special operations for the
  887. types SEQ OF and SET OF.  ast really has no built in types at all, it uses the
  888. ones  of  the  target  language  and  has a table containing the type specific
  889. operations e. g. for reading and writing. Both ast and IDL allow attributes of
  890. user-defined  types.  In  ast  the  type specific operations for predefined or
  891. user-defined types are easily expressed by macros using  the  target  language
  892. directly.  IDL offers an assertion language whereas ast does not. IDL provides
  893. a mechanism to modify existing specifications.  The module feature of ast  can
  894. be  used to extend existing specifications.  From ast, readers and writers are
  895. requested with simple command line options instead  of  complicated  syntactic
  896. constructs.   ast  does  not  support  representation  specifications, because
  897. representations are much more easily expressed using the types of  the  target
  898. language   directly.    Summarizing,   we  consider  ast  to  have  a  simpler
  899.  
  900.  
  901.  
  902.  
  903.  
  904.  
  905.  
  906.  
  907.  
  908.  
  909.                                                                             12
  910.  
  911.  
  912. specification method and to generate more powerful features  like  aggregates,
  913. reversal of lists, and graph browsers.
  914.  
  915. 4.6.  Object-Oriented Languages
  916.  
  917.      The extension mechanism of ast is exactly the same as single  inheritance
  918. in  object-oriented  languages like e. g. Simula [DMN70] or Smalltalk [Gol84].
  919. The hierarchy introduced by the extension mechanism  corresponds  directly  to
  920. the  class  hierarchy of object-oriented languages.  The notions base type and
  921. superclass both represent the same concept. Messages  and  virtual  procedures
  922. are out of the scope of ast.  Virtual procedures or object specific procedures
  923. might be simulated with procedure-valued attributes.  Table 4  summarizes  the
  924. corresponding  notions  of  trees  (ast), type extensions, and object-oriented
  925. programming.
  926.  
  927. Table 4: Comparison of notions from the areas of trees, types, and object-oriented programming
  928.  
  929.        trees              types             object-oriented programming
  930.        ________________________________________________________________
  931.        node type          record type       class
  932.        -                  base type         superclass
  933.        -                  derived type      subclass
  934.        attribute, child   record field      instance variable
  935.        tree node          record variable   object, instance
  936.        -                  extension         inheritance
  937.                        
  938.  
  939.  
  940.  
  941.  
  942.  
  943.                                          
  944.  
  945.  
  946.  
  947.  
  948.  
  949.  
  950.  
  951.  
  952.  
  953. 4.7.  Tree Grammars
  954.  
  955.      Conventional tree grammars are characterized by the fact that all  right-
  956. hand  sides start with a terminal symbol. They are used for the description of
  957. string languages that represent trees  in  prefix  form.   ast  specifications
  958. describe  trees  which  are  represented by (absolute) pointers from parent to
  959. child nodes. If we shift the names of node types of ast specifications to  the
  960. beginning  of the right-hand side and interpret them as terminals we arrive at
  961. conventional tree grammars. That is exactly what is  done  by  the  tree/graph
  962. writer  procedures.  They  write a tree/graph in prefix form and prepend every
  963. node with the name of its node type.  That is necessary to be able to  perform
  964. the read operation.
  965.  
  966. 5.  Summary
  967.  
  968.      We presented the tool ast, a generator for abstract syntax  trees,  which
  969. supports  the  definition  and manipulation of graph-like data structures. The
  970. records which define a graph and their relationships are specified by  a  for-
  971. malism  based  on  context-free grammars. The data structures may be decorated
  972. with attributes of arbitrary types. The tool generates a program  module  con-
  973. taining  a  set  of declarations to define the data structure and various pro-
  974. cedures to manipulate it. There are procedures to construct and destroy  nodes
  975. or graphs, to read and write graphs from (to) files, and to traverse graphs in
  976. some commonly used manners. The mentioned readers and writers process ascii as
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.                                                                             13
  988.  
  989.  
  990. well as binary graph representations.
  991.  
  992.      The advantages of this approach are: record aggregates are provided which
  993. allow  a  concise notation for node creation. It is possible to build trees by
  994. writing terms. The extension mechanism avoids  chain  rules  and  allows,  for
  995. example  lists  with  elements of different types. Input/output procedures for
  996. records and complete graphs  are  provided.  The  output  procedures  and  the
  997. interactive  graph browser facilitate the debugging phase as they operate on a
  998. readable level and know the data structure.  The user does not have to  attend
  999. to  algorithms for traversing graphs. He/she is freed from the task of writing
  1000. large amounts of relatively simple code.  All of these features  significantly
  1001. increase programmer productivity.
  1002.  
  1003. References
  1004.  
  1005. [Bie89]
  1006.      F. Bieler, An Interpreter for Chandy/Misra's UNITY, internal  paper,  GMD
  1007.      Forschungsstelle an der Universitat Karlsruhe, 1989.
  1008.  
  1009. [DMN70]
  1010.      O. Dahl, B. Myrhaug and K. Nygaard, SIMULA  67  Common  Base  Language  -
  1011.      Publication S-22, Norwegian Computing Center, Oslo, 1970.
  1012.  
  1013. [Gol84]
  1014.      A.  Goldberg,  Smalltalk-80:  The  Interactive  Programming  Environment,
  1015.      Addison Wesley, Reading, MA, 1984.
  1016.  
  1017. [Gro88]
  1018.      J. Grosch, Generators for High-Speed Front-Ends, LNCS 371,  (Oct.  1988),
  1019.      81-92, Springer Verlag.
  1020.  
  1021. [GrV88]
  1022.      J. Grosch and B. Vielsack, The Parser Generators Lalr and  Ell,  Compiler
  1023.      Generation   Report  No.  8,  GMD  Forschungsstelle  an  der  Universitat
  1024.      Karlsruhe, Apr. 1988.
  1025.  
  1026. [Gro89]
  1027.      J. Grosch, Ag - An Attribute  Evaluator  Generator,  Compiler  Generation
  1028.      Report  No.  16,  GMD Forschungsstelle an der Universitat Karlsruhe, Aug.
  1029.      1989.
  1030.  
  1031. [Gro91]
  1032.      J. Grosch,  Ast  -  A  Generator  for  Abstract  Syntax  Trees,  Compiler
  1033.      Generation  Report  No.  15,  GMD  Forschungsstelle  an  der  Universitat
  1034.      Karlsruhe, Sep. 1991.
  1035.  
  1036. [JWM85]
  1037.      K. Jensen, N. Wirth, A. B. Mickel and J. F. Miner, Pascal User Manual and
  1038.      Report, Springer Verlag, New York, 1985.  Third Edition.
  1039.  
  1040. [Joh75]
  1041.      S. C. Johnson, Yacc -  Yet Another  Compiler-Compiler,  Computer  Science
  1042.      Technical  Report  32, Bell Telephone Laboratories, Murray Hill, NJ, July
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.                                                                             14
  1054.  
  1055.  
  1056.      1975.
  1057.  
  1058. [Knu68]
  1059.      D. E. Knuth, Semantics of Context-Free  Languages,  Mathematical  Systems
  1060.      Theory 2, 2 (June 1968), 127-146.
  1061.  
  1062. [Knu71]
  1063.      D.  E.  Knuth,   Semantics   of   Context-free   Languages:   Correction,
  1064.      Mathematical Systems Theory 5, (Mar. 1971), 95-96.
  1065.  
  1066. [Lam87]
  1067.      D. A. Lamb, IDL: Sharing Intermediate Representations, ACM  Trans.  Prog.
  1068.      Lang. and Systems 9, 3 (July 1987), 297-318.
  1069.  
  1070. [Mar90]
  1071.      M. Martin, Entwurf und Implementierung  eines  Ubersetzers  von  Modula-2
  1072.      nach  C, Diplomarbeit, GMD Forschungsstelle an der Universitat Karlsruhe,
  1073.      Feb. 1990.
  1074.  
  1075. [NNG89]
  1076.      J. R. Nestor, J. M. Newcomer, P. Giannini  and  D.  L.  Stone,  IDL:  The
  1077.      Language and its Implementation, Prentice Hall, Englewood Cliffs, 1989.
  1078.  
  1079. [Par88]
  1080.      J. C. H. Park, y+: A Yacc  Preprocessor  for  Certain  Semantic  Actions,
  1081.      SIGPLAN Notices 23, 6 (1988), 97-106.
  1082.  
  1083. [SDD86]
  1084.      J. T. Schwartz, R. B. K. Dewar, E. Dubinsky and E. Schonberg, Programming
  1085.      with Sets - An Introduction to SETL, Springer Verlag, New York, 1986.
  1086.  
  1087. [WGS89]
  1088.      W. M. Waite, J. Grosch and F. W. Schroer, Three Compiler  Specifications,
  1089.      GMD-Studie  Nr.  166,  GMD Forschungsstelle an der Universitat Karlsruhe,
  1090.      Aug. 1989.
  1091.  
  1092. [Wir85]
  1093.      N. Wirth, Programming in Modula-2,  Springer  Verlag,  Heidelberg,  1985.
  1094.      Third Edition.
  1095.  
  1096. [Wir88a]
  1097.      N. Wirth, Type Extensions, ACM Trans. Prog. Lang. and Systems 10, 2 (Apr.
  1098.      1988), 204-214.
  1099.  
  1100. [Wir88b]
  1101.      N. Wirth, From Modula to Oberon, Software-Practice  &  Experience  18,  7
  1102.      (July 1988), 661-670.
  1103.  
  1104. [Wir88c]
  1105.      N. Wirth, The Programming Language Oberon, Software-Practice & Experience
  1106.      18, 7 (July 1988), 671-690.
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.                                                                              1
  1119.  
  1120.  
  1121. Contents
  1122.  
  1123.         Abstract ........................................................    1
  1124. 1.      Introduction ....................................................    1
  1125. 2.      Specification Language ..........................................    2
  1126. 2.1.    Node Types ......................................................    2
  1127. 2.2.    Children ........................................................    2
  1128. 2.3.    Attributes ......................................................    3
  1129. 2.4.    Extensions ......................................................    3
  1130. 2.5.    Modules .........................................................    4
  1131. 2.6.    Properties ......................................................    4
  1132. 2.7.    Reversal of Lists ...............................................    4
  1133. 2.8.    Target Code .....................................................    5
  1134. 2.9.    Type Specific Operations ........................................    5
  1135. 3.      Generated Program Module and its Use ............................    6
  1136. 4.      Related Research ................................................   10
  1137. 4.1.    Variant Records .................................................   10
  1138. 4.2.    Type Extensions .................................................   10
  1139. 4.3.    Context-Free Grammars ...........................................   10
  1140. 4.4.    Attribute Grammars ..............................................   11
  1141. 4.5.    Interface Description Language (IDL) ............................   11
  1142. 4.6.    Object-Oriented Languages .......................................   12
  1143. 4.7.    Tree Grammars ...................................................   12
  1144. 5.      Summary .........................................................   12
  1145.         References ......................................................   13
  1146.  
  1147.  
  1148.  
  1149.  
  1150.  
  1151.  
  1152.  
  1153.  
  1154.  
  1155.  
  1156.  
  1157.  
  1158.  
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166.  
  1167.  
  1168.  
  1169.  
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179.